package eval.results;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import eval.utilities.configuration.ExperimentConfiguration;

/**
 * Writes the IResultsData object into a csv file
 * */
public class ResultsToCsv {
	public final static String PLACEMENT_FOLDER = 
			ExperimentConfiguration.getSingleton().placementLogsPath;

	private IResultsData results;
	private String fileName;

	public ResultsToCsv(IResultsData results, String fileName) {
		this.results = results;
		this.fileName = fileName;
	}

	public void write() {
		FileOutputStream fout;
		try {
			String filePath = PLACEMENT_FOLDER + fileName;
			fout = new FileOutputStream(filePath);
			System.out.println("\nWriting " + filePath);
			write(fout, results);
			fout.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private void write(FileOutputStream fout, IResultsData results)
			throws IOException {

		// create external list (one list for each tick)
		List<List<Double>> tickData = loadData(fout, results);
		Integer tick = 0;
		for (List<Double> resultsInTick : tickData) {
			fout.write(tick.toString().getBytes());
			for (Double value : resultsInTick) {
				String s = ", " + value.toString();
				fout.write(s.getBytes());
			}
			tick++;
			fout.write("\n".getBytes());
		}
	}

	private List<List<Double>> loadData(FileOutputStream fout,
			IResultsData results) throws IOException {
		int ticks = results.getExperimentTicks();
		List<String> fieldNames = new ArrayList<String>();
		fieldNames.add("Tick");

		List<List<Double>> tickData = new ArrayList<List<Double>>(ticks);
		for (int i = 0; i < ticks; i++) {
			// add internal list (a double for each result of that tick)
			tickData.add(new ArrayList<Double>(30));
		}

		int currentResultIndex = 1;
		for (Method m : results.getClass().getDeclaredMethods()) {
			if (m.getName().startsWith("get")) {
				Class<?> clazz = m.getReturnType();
				String fieldName = m.getName().substring(3);

				double[] doubleArray = new double[1];
				if (clazz.equals(doubleArray.getClass())) {
					fieldNames.add(fieldName);
					// System.out.println(m);
					try {
						double[] res = (double[]) m.invoke(results, null);
						for (int i = 0; i < ticks; i++) {
							tickData.get(i).add(res[i]);
						}
						currentResultIndex++;
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
				int c =0;
				int[] intArray = new int[1];
				if (clazz.equals(intArray.getClass())) {
					fieldNames.add(fieldName);
					try {
						int[] res = (int[]) m.invoke(results, null);
						for (int i = 0; i < ticks; i++) {
//							System.out.println("i= "+i +"  currentResultIndex= "+currentResultIndex);
							tickData.get(i).add(new Double(res[i]));
						}
						currentResultIndex++;
					} catch (Exception e) {
						System.out.println(fieldName);
						e.printStackTrace();
					}
				}
			}
		}
		fout.write(fieldNames.get(0).getBytes());
		for (String fieldName : fieldNames.subList(1, fieldNames.size())) {
			String field = ", " + fieldName;
			fout.write(field.getBytes());
		}
		fout.write("\n".getBytes());
		return tickData;
	}
}
